Completed
Push — master ( 7b524c...0d3c7c )
by Ruben de
05:15 queued 02:24
created

multisigStackFixtures.constructor   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
c 1
b 0
f 0
nc 5
dl 0
loc 32
rs 8.5806
nop 0

2 Functions

Rating   Name   Duplication   Size   Complexity  
A u.map 0 3 1
A c.map 0 3 1
1
/* jshint -W101, -W098 */
2
/* global window */
3
var assert = require('assert');
4
var bitcoin = require('bitcoinjs-lib');
5
var SizeEstimation = require("../lib/size_estimation");
6
7
var varIntFixtures = [
8
    [0, 1],
9
    [1, 1],
10
    [252, 1],
11
    [253, 3],
12
    [254, 3],
13
    [65534, 3],
14
    [65535, 5],
15
    [65536, 5],
16
    [Math.pow(2, 31), 5],
17
    [Math.pow(2, 32) - 2, 5],
18
    [Math.pow(2, 32) - 1, 9],
19
    [Math.pow(2, 32), 9],
20
21
    // don't go above this, is signed int territory, PHP complains
22
    // nodejs?
23
    [0x7fffffffffffffff, 9]
24
];
25
26
var scriptDataLenFixtures =  [
27
    [0, 1],
28
    [1, 1],
29
    [74, 1],
30
    [75, 2],
31
    [76, 2],
32
    [254, 2],
33
    [255, 2],
34
    [256, 3],
35
    [65534, 3],
36
    [65535, 3],
37
    [65536, 5]
38
];
39
40
var multisigStackFixtures = (function() {
41
    var u = ['5KW8Ymmu8gWManGggZZQJeX7U3pn5HtcqqsVrNUbc1SUmVPZbwp',
42
        '5KCV94YBsrJWTdk6cQWJxEd25sH8h1cGTpJnCN6kLMLe4c3QZVr',
43
        '5JUxGateMWVBsBQkAwSRQLxyaQXhsch4EStfC62cqdEf2zUheVT'
44
    ];
45
    var c = ['L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
46
        'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
47
        'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
48
    ];
49
    var uncompressed = u.map(function(wif) {
50
        return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin);
51
    });
52
    var compressed = c.map(function(wif) {
53
        return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin);
54
    });
55
56
    var fixtures = [];
57
    for (var i = 0; i < 3; i++) {
58
        var keys = [];
59
        var j;
60
        for (j = 0; j < i; j++) {
61
            keys.push(uncompressed[j].getPublicKeyBuffer());
62
        }
63
        for (j = i; j < 3; j++) {
64
            keys.push(compressed[j].getPublicKeyBuffer());
65
        }
66
67
        fixtures.push([bitcoin.script.multisig.output.encode(2, keys)]);
68
    }
69
70
    return fixtures;
71
})();
72
73
// test fixtures of every possible representation of multisig
74
var multisigFormFixtures = (function() {
75
    var c = ['L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
76
        'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
77
        'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
78
    ];
79
    var keys = c.map(function(wif) {
80
        return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin).getPublicKeyBuffer();
81
    });
82
    var multisig = bitcoin.script.multisig.output.encode(2, keys);
83
    var bareSize = 1/*op0*/ + 2 * (1 + SizeEstimation.SIZE_DER_SIGNATURE);
84
85
    var bareSig = 1 + bareSize;
86
    var p2shSig = 3 + bareSize + 2 + multisig.length;
87
88
    var p2wshHash = bitcoin.crypto.sha256(multisig);
89
    var p2wshScript = bitcoin.script.witnessScriptHash.output.encode(p2wshHash);
90
91
    var nestedSig = 1 + 1 + p2wshScript.length;
92
    var witSize = 1 + 2 * (1 + SizeEstimation.SIZE_DER_SIGNATURE);
93
    var nestedWit = witSize + 1 + 1 + multisig.length;
94
95
    return [
96
        [multisig, false, null, null, bareSig, 0],
97
        [multisig, false, multisig, null, p2shSig, 0],
98
        [multisig, true, null, multisig, 1, nestedWit],
99
        [multisig, true, p2wshScript, multisig, nestedSig, nestedWit]
100
    ];
101
})();
102
103
function makeUtxo(script, rs, ws) {
104
    var utxo = {
105
        scriptpubkey_hex: script.toString('hex'),
106
        value: 100000000
107
    };
108
    if (rs instanceof Buffer) {
0 ignored issues
show
Bug introduced by
The variable Buffer seems to be never declared. If this is a global, consider adding a /** global: Buffer */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
109
        utxo.redeem_script = rs.toString('hex');
110
    }
111
    if (ws instanceof Buffer) {
112
        utxo.witness_script = ws.toString('hex');
113
    }
114
    return utxo;
115
}
116
117
// test fixtures of every possible representation of multisig
118
var multisigUtxoFixtures = (function() {
119
    var c = ['L1Tr4rPUi81XN1Dp48iuva5U9sWxU1eipgiAu8BhnB3xnSfGV5rd',
120
        'KwUZpCvpAkUe1SZj3k3P2acta1V1jY8Dpuj71bEAukEKVrg8NEym',
121
        'Kz2Lm2hzjPWhv3WW9Na5HUKi4qBxoTfv8fNYAU6KV6TZYVGdK5HW'
122
    ];
123
    var keys = c.map(function(wif) {
124
        return bitcoin.ECPair.fromWIF(wif, bitcoin.networks.bitcoin).getPublicKeyBuffer();
125
    });
126
    var multisig = bitcoin.script.multisig.output.encode(2, keys);
127
    var bareSize = 1/*op0*/ + 2 * (1 + SizeEstimation.SIZE_DER_SIGNATURE);
128
129
    var bareSig = 1 + bareSize;
130
    var p2shSig = 3 + bareSize + 2 + multisig.length;
131
132
    var p2wshHash = bitcoin.crypto.sha256(multisig);
133
    var p2wshScript = bitcoin.script.witnessScriptHash.output.encode(p2wshHash);
134
135
    var nestedSig = 1 + 1 + p2wshScript.length;
136
    var witSize = 1 + 2 * (1 + SizeEstimation.SIZE_DER_SIGNATURE);
137
    var nestedWit = witSize + 1 + 1 + multisig.length;
138
139
    var multisigHash160 = bitcoin.crypto.hash160(multisig);
140
    var multisigP2sh = bitcoin.script.scriptHash.output.encode(multisigHash160);
141
142
    var multisigSha256 = bitcoin.crypto.sha256(multisig);
143
    var multisigP2wsh = bitcoin.script.witnessScriptHash.output.encode(multisigSha256);
144
145
    var p2wshHash160 = bitcoin.crypto.hash160(multisigP2wsh);
146
    var p2wshP2sh = bitcoin.script.scriptHash.output.encode(p2wshHash160);
147
148
    var bareUtxo = makeUtxo(multisig, null, null);
149
    var p2shUtxo = makeUtxo(multisigP2sh, multisig, null);
150
    var p2wshUtxo = makeUtxo(multisigP2wsh, null, multisig);
151
    var p2shP2wshUtxo = makeUtxo(p2wshP2sh, p2wshScript, multisig);
152
153
    return [
154
        [bareUtxo, bareSig, 0],
155
        [p2shUtxo, p2shSig, 0],
156
        [p2wshUtxo, 1, nestedWit],
157
        [p2shP2wshUtxo, nestedSig, nestedWit]
158
    ];
159
})();
160
161
describe('getLengthForVarInt', function() {
162
    varIntFixtures.map(function(fixture) {
163
        var inputLen = fixture[0];
164
        var expectSize = fixture[1];
165
        it('works for `' + inputLen + '` (equals ' + expectSize + ')', function(cb) {
166
            var result = SizeEstimation.getLengthForVarInt(inputLen);
167
            assert.equal(expectSize, result);
168
            cb();
169
        });
170
    });
171
});
172
173
describe('getLengthForScriptPush', function() {
174
    scriptDataLenFixtures.map(function(fixture) {
175
        var inputLen = fixture[0];
176
        var expectSize = fixture[1];
177
        it(' works for ' + inputLen + '` (equals ' + expectSize + ')', function(cb) {
178
            var result = SizeEstimation.getLengthForScriptPush(inputLen);
179
            assert.equal(expectSize, result);
180
            cb();
181
        });
182
    });
183
});
184
185
describe("estimateMultisigStackSize", function() {
186
    multisigStackFixtures.map(function(fixture) {
187
        it("works for multisig scripts with the keys", function(cb) {
188
            var script = fixture[0];
189
            assert.ok(bitcoin.script.multisig.output.check(script));
190
            var decoded = bitcoin.script.multisig.output.decode(script);
191
            var estimation = SizeEstimation.estimateMultisigStackSize(decoded.m, decoded.pubKeys);
192
193
            assert.equal("object", typeof estimation);
194
            assert.equal(2, estimation.length);
195
196
            var scriptSize = estimation[1];
197
            assert.equal(script.length, scriptSize);
198
199
            var stackSizes = estimation[0];
200
            assert.equal(1 + decoded.m, stackSizes.length);
201
            assert.equal(0, stackSizes[0]);
202
            for (var i = 0; i < decoded.m; i++) {
203
                assert.equal(SizeEstimation.SIZE_DER_SIGNATURE, stackSizes[1 + i]);
204
            }
205
            cb();
206
        });
207
    });
208
209
    multisigFormFixtures.map(function(fixture) {
210
        it("deals with different representations", function(cb) {
211
            var script = fixture[0];
212
            var isWit = fixture[1];
213
            var rs = fixture[2];
214
            var ws = fixture[3];
215
            var expectSig = fixture[4];
216
            var expectWit = fixture[5];
217
218
            assert.ok(bitcoin.script.multisig.output.check(script));
219
            var multisig = bitcoin.script.multisig.output.decode(script);
220
221
            var stackEst = SizeEstimation.estimateMultisigStackSize(multisig.m, multisig.pubKeys);
222
            var stackSizes = stackEst[0];
223
224
            var est = SizeEstimation.estimateStackSignatureSize(stackSizes, isWit, rs, ws);
225
            assert.equal("object", typeof est);
226
            assert.equal(2, est.length);
227
228
            var foundSigSize = est[0];
229
            var foundWitSize = est[1];
230
231
            assert.equal(foundSigSize, expectSig);
232
            assert.equal(foundWitSize, expectWit);
233
            cb();
234
        });
235
    });
236
237
    multisigUtxoFixtures.map(function(fixture) {
238
        it("deals with different representations", function(cb) {
239
            var utxo = fixture[0];
240
            var expectSig = fixture[1];
241
            var expectWit = fixture[2];
242
243
            var estimate = SizeEstimation.estimateUtxo(utxo);
244
245
            assert.equal(estimate.scriptSig, expectSig);
246
            assert.equal(estimate.witness, expectWit);
247
            cb();
248
        });
249
    });
250
});
251